package com.base.util;

import com.base.util.intfac.ParseUtilConvert;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Shisan on 2017/10/16.
 * 反射工具类
 */
public class ReflectUtil {

    /**
     * 获取类下的所有属性，包含继承，私有
     * @param clazz
     * @return
     */
    public static List<Field> getAllField(Class<?> clazz){
        List<Field> list = new ArrayList<Field>();
        Field fields[] = clazz.getDeclaredFields();
        if(fields!=null && fields.length>0){
            for(Field f:fields){
                list.add(f);
            }
        }
        if(clazz.getSuperclass()!=null){
            list.addAll(getAllField(clazz.getSuperclass()));
        }
        return list;
    }

    public static Field getFieldByName(String fieldName,Class<?> clazz){
        Field field;
        try {
            field=clazz.getDeclaredField(fieldName);
            return field;
        } catch (NoSuchFieldException e) {
        }
        return getFieldByName(fieldName,clazz.getSuperclass());
    }

    public static void setFieldValue(Field f,Object instance,Object value) throws Exception{
        if(f.isAccessible()){
            f.set(instance,value);
        }else{
            f.setAccessible(false);
            f.set(instance,value);
            f.setAccessible(true);
        }
    }

    public static Method getReadMethodByField(Field f) throws Exception{
        PropertyDescriptor pd = new PropertyDescriptor(f.getName(), f.getDeclaringClass());
        return pd.getReadMethod();
    }

    public static Method getWriteMethodByField(Field f) throws Exception{
        PropertyDescriptor pd = new PropertyDescriptor(f.getName(), f.getDeclaringClass());
        return pd.getWriteMethod();
    }

    public static Object invokeMethod(Class<?> clazz,Object instance,String methodName,Class<?> []types,Object...params){
        if(clazz == null) return null;
        try{
            Method m = clazz.getDeclaredMethod(methodName,types);
            return m.invoke(instance,params);
        }catch (Exception e){
        }
        return invokeMethod(clazz.getSuperclass(),instance,methodName,types,params);
    }

    public static boolean hasAnnocation(Class<?> clazz,Class annocation){
        return clazz.getAnnotation(annocation)!=null;
    }

    public static boolean hasAnnocation(Field f,Class annocation){
        return f.getAnnotation(annocation)!=null;
    }

    public static boolean hasAnnocation(Method m,Class annocation){
        return m.getAnnotation(annocation)!=null;
    }

    public static <T>T simpleMapToBean(Map<String,Object> map, Class<T> clazz, ParseUtilConvert pc){
        T bean = null;
        try {
            bean = clazz.getConstructor().newInstance();
        } catch (Exception e) {
            return null;
        }
        Field f;
        Method r;
        Object v;
        for(Map.Entry<String,Object> m:map.entrySet()){
            f=null;
            r=null;
            f=getFieldByName(m.getKey(),clazz);
            if(f!=null){
                try {
                    v=ParseUtil.parse(m.getValue(),f.getType(),pc);
                    r=getWriteMethodByField(f);
                    r.invoke(bean,v);
                } catch (Exception e) {
                }
            }
        }
        return bean;
    }

}
